package indi.a709924470.scpwiki;

import android.support.annotation.Nullable;
import android.util.Log;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import indi.a709924470.scpwiki.beans.WikiItems;
import indi.a709924470.scpwiki.beans.WikiSubItems;

import static android.content.ContentValues.TAG;

/**
 * Created by Walter Ji on 2017/12/21.
 */

public class ParseWikiPage {
    private boolean success = false;
    private Document doc;
    private String title = null;
    private String key;
    private String error;

    public ParseWikiPage(@Nullable String pageurl,@Nullable String keyword){
        String url = (pageurl == null || pageurl == "") ? "http://scp-wiki-cn.wikidot.com/" : pageurl;
        key = keyword;
        ExecutorService es = Executors.newSingleThreadExecutor();
        Future<Document> fd = es.submit(new netThread(url));
        try {
            doc = fd.get(10, TimeUnit.SECONDS);
            success = true;
        } catch (Exception e) {
            Log.e("Shit!", "ParseWikiPage: "+e.toString(),e);
            error = e.getLocalizedMessage();
            success = false;
        }
        Log.d("Info", "ParseWikiPage: New Instance.");
        Log.d("Info", "ParseWikiPage: url = " + url);
        Log.d("Info", "ParseWikiPage: key = " + key);
        Log.d("Info", "ParseWikiPage: isSuccess = " + success);
        Log.d("Info", "ParseWikiPage: Page Title = " + doc.title());
    }

    public ParseWikiPage(@Nullable String pageurl){
        String url = (pageurl == null || pageurl == "") ? "http://scp-wiki-cn.wikidot.com/" : pageurl;
        key = null;
        ExecutorService es = Executors.newSingleThreadExecutor();
        Future<Document> fd = es.submit(new netThread(url));
        try {
            doc = fd.get(10, TimeUnit.SECONDS);
            success = true;
        } catch (Exception e) {
            Log.e("Shit!", "ParseWikiPage: "+e.toString(),e);
            error = e.getLocalizedMessage();
            success = false;
        }
        Log.d("Info", "ParseWikiPage: New Instance.");
        Log.d("Info", "ParseWikiPage: url = " + url);
        Log.d("Info", "ParseWikiPage: key = " + key);
        Log.d("Info", "ParseWikiPage: isSuccess = " + success);
        Log.d("Info", "ParseWikiPage: Page Title = " + doc.title());
    }

    public String getCharset(){
        if (!success) return null;
        return doc.charset().name();
    }

    private Element getSideNodes(){
        if(!success) return null;
        Elements es = doc.getElementsByClass("side-block");
        for (Element e : es){
            for (Element ex : e.children()){
                if (ex.className().contains("heading")){
                    return e;
                }
            }
        }
        return null;
    }

    public List<WikiItems> sideitems(){
        if (!success) return null;
        Element emt = getSideNodes();
        List<WikiItems> arr = new ArrayList<>();
        String itx = null;
        WikiItems wi = new WikiItems();
        List<WikiSubItems> sar = new ArrayList<>();
        for (Element i : emt.children()){
            if (i.className().contains("heading")) {
                if (itx != i.text()) {
                    wi.wsi = sar;
                    arr.add(wi);
                    wi = new WikiItems();
                    wi.name = i.text();
                    sar = new ArrayList<>();
                }
                continue;
            }else {
                for (Element j : i.children()) {
                    if (!j.tagName().equals("a")) continue;
                    WikiSubItems wsi = new WikiSubItems();
                    wsi.name = j.text();
                    wsi.url = j.attr("abs:href");
                    sar.add(wsi);
                }
            }
        }
        return arr;
    }

    private Element getPageContent(){
        if (!success) return null;
        int f = 0;
        Element emt = doc.getElementById("main-content");
        Element e2 = null;
        for (Element e1 : emt.children()){
            if(e1.id().equals("page-title")){
                title = e1.text();
                f++;
            }
            if(e1.id().equals("page-content")){
                e2 = e1;
                f++;
            }
            if(e2 == e1 && f == 2) break;
        }
        return e2;
    }

    private Elements getJavaScripts(){
        if (!success) return null;
        List<Element> le = new ArrayList<>();
        Elements els = doc.getElementsByTag("style");
        for (Element el : els){
            if (el.attr("src").contains("common") && el.attr("src").contains("javascript")){
                le.add(el);
            }
        }
        return new Elements(le);
    }

    private Elements getStylesheets(){
        if (!success) return null;
        List<Element> le = new ArrayList<>();
        Elements ell = doc.getElementsByTag("link");
        Elements els = doc.getElementsByTag("style");
        for (Element el : ell){
        }
        for (Element el : els){
            le.add(el);
        }
        return new Elements(le);
    }

    public String parseContent(){
        if (!success) return null;
        Element pgct = getPageContent();
        pgct.getElementsByClass("footer-wikiwalk-nav").remove();
        //pgct.getElementsByTag("a").removeAttr("href");
        StringBuilder sb = new StringBuilder();
        sb.append("<meta http-equiv=\"content-type\" content=\"text/html;charset="+doc.charset()+"\">");
        sb.append(getJavaScripts().html());
        sb.append(pgct.html());
        Elements els = getStylesheets();
        for (Element el : els){
            sb.append("\r\n<"+el.tag()+" "+el.attributes()+">");
            sb.append(el.html());
            sb.append("\r\n</"+el.tag()+">");
        }
        return sb.toString();
    }

    public List<WikiItems> pageitems(){
        if (!success) return null;
        Element em = getPageContent();
        List<WikiItems> lwi = new ArrayList<>();
        String itx = null;
        WikiItems wi = new WikiItems();
        List<WikiSubItems> sar = new ArrayList<>();
        boolean f = false;
        if (em == null){
            Log.d(TAG,"em is NULL!");
            return nullLWI();
        }
        if(em.children() == null){
            Log.d(TAG,"em Has NO Children!");
            return nullLWI();
        }
        while (em.children().size() <= 2) {
            Log.d(TAG,"em size is less than 2");
            em = em.children().first();
        }
        for (Element e : em.children()) {
            if (e.id().contains("to") && e.tagName() == "h1" && itx != e.text() && !f) {
                f = true;
                wi.wsi = sar;
                lwi.add(wi);
                wi = new WikiItems();
                itx = e.text();
                wi.name = e.text();
                sar = new ArrayList<>();
                continue;
            }
            if(f && e.tagName() == "ul") {
                f = false;
                for (Element i : e.children()) {
                    WikiSubItems wsi = new WikiSubItems();
                    wsi.name = i.text();
                    wsi.url = i.getElementsByTag("a").attr("abs:href");
                    sar.add(wsi);
                }
            }
        }
        return lwi;
    }

    private List<WikiItems> nullLWI(){
        return new ArrayList<>();
    }
    private List<WikiSubItems> nullLSI(){
        return new ArrayList<>();
    }

    public String getError(){
        return isSuccess() ? null : error;
    }

    public boolean isContentPage(){return false;}

    public boolean isSuccess() {
        return success;
    }

    public boolean hasTitle(){
        return title == null;
    }

    public String getTitle(){
        if (title == null){
            Element e = doc.getElementById("page-title");
            return e.text();
        }
        return title;
    }

    public Document getDoc() {
        return isSuccess() ? doc : null;
    }

    @Override
    public String toString() {
        return isSuccess() ? doc.html() : null;
    }

    private static class netThread implements Callable<Document> {
        private String url;
        public netThread(String url){
            this.url = url;
        }

        @Override
        public Document call() throws Exception {
            return Jsoup.connect(url)
                    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36")
                    .timeout(10000)
                    .get();
        }
    }
}
